#include <QLineEdit>
#include "Editor/formattingtoolbar.h"
#include "Preferences/preferences.h"

const QRgb FormattingToolBar::maskedColour = qRgb(255, 0, 0);

FormattingToolBar::FormattingToolBar(FormattedEditor *newEditor): QToolBar(newEditor)
{
	editor = newEditor;

	bold = new QAction(QIcon(":mainToolbarIcons/images/formattingToolbar/bold.png"),
					"Bold", this);
	italic = new QAction(QIcon(":mainToolbarIcons/images/formattingToolbar/italic.png"),
					  "Italic", this);
	underline = new QAction(QIcon(":mainToolbarIcons/images/formattingToolbar/underline.png"),
					 "Underline", this);
	font = new QFontComboBox(this);
	fontSize = new QComboBox(this);

	QActionGroup *alignGroup = new QActionGroup(this);
	leftAlign = new QAction(QIcon(":mainToolbarIcons/images/formattingToolbar/left_align.png"),
					 "Left align", alignGroup);
	centreAlign = new QAction(QIcon(":mainToolbarIcons/images/formattingToolbar/center_align.png"),
					   "Centre align", alignGroup);
	rightAlign = new QAction(QIcon(":mainToolbarIcons/images/formattingToolbar/right_align.png"),
					  "Right align", alignGroup);
	justifyAlign = new QAction(QIcon(":mainToolbarIcons/images/formattingToolbar/just_align.png"),
						"Justify align", alignGroup);

	bullets = new QAction(QIcon(":mainToolbarIcons/images/formattingToolbar/bullets.png"),"Add Bullet Points", this);
	numbers = new QAction(QIcon(":mainToolbarIcons/images/formattingToolbar/numbers.png"),"Add Numbered Points", this);

	//load the images for the colour icons and find the masked colours
	colourImage = new QImage(":mainToolbarIcons/images/formattingToolbar/text_colour.png");
	backColourImage = new QImage(":mainToolbarIcons/images/formattingToolbar/bucket.png");
	colourMaskIndex = colourImage->colorTable().indexOf(maskedColour);
	backColourMaskIndex = backColourImage->colorTable().indexOf(maskedColour);

	colour = new QAction(QIcon(QPixmap::fromImage(*colourImage)),"Set Foreground Colour", this);
	textBackgroundColour = new QAction(QIcon(QPixmap::fromImage(*backColourImage)),"Set Background Colour", this);

	image = new QAction(QIcon(":mainToolbarIcons/images/formattingToolbar/image.png"),"Add Image", this);
	table = new QAction(QIcon(":mainToolbarIcons/images/formattingToolbar/table.png"),"Add Table", this);

	bold->setCheckable(true);
	italic->setCheckable(true);
	underline->setCheckable(true);

	fontSize->addItems(QStringList() << "6" << "7" << "8" << "9" << "10"
			   << "11" << "12" << "14" << "16" << "18" << "20" << "22"
			   << "24" << "26" << "28" << "36" << "48" << "72");
	fontSize->setEditable(true);

	fontSize->setFocusPolicy(Qt::NoFocus);
	leftAlign->setCheckable(true);
	centreAlign->setCheckable(true);
	rightAlign->setCheckable(true);
	justifyAlign->setCheckable(true);

	bullets->setCheckable(true);
	numbers->setCheckable(true);

	setIconSize(QSize(16, 16));
	addActions(QList<QAction *>() << bold << italic << underline);
	addSeparator();
	addWidget(font);
	addWidget(fontSize);
	addSeparator();
	addActions(QList<QAction *>() << leftAlign << centreAlign
				   << rightAlign << justifyAlign);
	addSeparator();
	//addActions(QList<QAction *>() << bullets << numbers);
	//addSeparator();
	addActions(QList<QAction *>() << colour << textBackgroundColour);
	addSeparator();
	addActions(QList<QAction *>() << image << table);

	// Connect text editor and formatting signals.
	connect(bold, SIGNAL(toggled(bool)), this, SLOT(setBold(bool)));
	connect(italic, SIGNAL(toggled(bool)), editor, SLOT(setFontItalic(bool)));
	connect(underline, SIGNAL(toggled(bool)), editor, SLOT(setFontUnderline(bool)));
	connect(font, SIGNAL(activated(QString)), this, SLOT(setFont()));
	connect(fontSize, SIGNAL(currentIndexChanged(QString)), this, SLOT(setFontSize()));
	connect(fontSize->lineEdit(), SIGNAL(returnPressed()), this, SLOT(setFontSize()));
	connect(leftAlign, SIGNAL(toggled(bool)), this, SLOT(setLeftAlign(bool)));
	connect(centreAlign, SIGNAL(toggled(bool)), this, SLOT(setCentreAlign(bool)));
	connect(rightAlign, SIGNAL(toggled(bool)), this, SLOT(setRightAlign(bool)));
	connect(justifyAlign, SIGNAL(toggled(bool)), this, SLOT(setJustifyAlign(bool)));
	connect(bullets, SIGNAL(toggled(bool)), this, SLOT(setBulletFormatter(bool)));
	connect(numbers, SIGNAL(toggled(bool)), this, SLOT(setNumberFormatter(bool)));
	connect(colour, SIGNAL(triggered()), this, SLOT(chooseFontColour()));
	connect(textBackgroundColour, SIGNAL(triggered()), this, SLOT(chooseFontBackgroundColor()));
	connect(image, SIGNAL(triggered()), this, SLOT(addImage()));
	connect(table, SIGNAL(triggered()), this, SLOT(addTable()));

	connect(editor, SIGNAL(selectionChanged()), this, SLOT(matchCurrentFormat()));
	connect(editor, SIGNAL(textChanged()), this,  SLOT(matchCurrentFormat()));

	matchCurrentFormat();
}

void FormattingToolBar::setBold(const bool newBold)
{
	if (newBold)
		editor->setFontWeight(QFont::Bold);
	else
		editor->setFontWeight(QFont::Normal);
}

void FormattingToolBar::setFont()
{
	editor->setCurrentFont(font->currentFont());
}

//sets the font size from the line edit
void FormattingToolBar::setFontSize()
{
	setFontSize(fontSize->lineEdit()->text());
}

void FormattingToolBar::setFontSize(const QString newSize)
{
	float size = newSize.toFloat();

	qDebug("line edit %f", size);

	if (size > 0)
		editor->setFontPointSize(size);

}

void FormattingToolBar::setLeftAlign(const bool align)
{
	if (align)
		editor->setAlignment(Qt::AlignLeft);
}

void FormattingToolBar::setCentreAlign(const bool align)
{
	if (align)
		editor->setAlignment(Qt::AlignHCenter);
}

void FormattingToolBar::setRightAlign(const bool align)
{
	if (align)
		editor->setAlignment(Qt::AlignRight);
}

void FormattingToolBar::setJustifyAlign(const bool align)
{
	if (align)
		editor->setAlignment(Qt::AlignJustify);
}

void FormattingToolBar::setBulletFormatter(const bool bulletsOn)
{
	editor->toggleList(bulletsOn, (int)QTextListFormat::ListDisc);

	if (bullets->isChecked())
	{
		numbers->blockSignals(true);
		numbers->setChecked(false);
		numbers->blockSignals(false);
	}
}

void FormattingToolBar::setNumberFormatter(const bool numbersOn)
{
	editor->toggleList(numbersOn, (int)QTextListFormat::ListDecimal);

	if (numbers->isChecked())
	{
		bullets->blockSignals(true);
		bullets->setChecked(false);
		bullets->blockSignals(false);
	}
}

/**
  * Shows a dialog which lets the user change colours, then fixes the toolbar icon to reflect the choice
  */
void FormattingToolBar::chooseFontColour()
{
	QColor newColour = QColorDialog::getColor(editor->textColor(), window(), "Choose font colour");

	if (newColour.isValid())
	{
		editor->setTextColor(newColour);

		//fix up the colour in the icon
		colourImage->setColor(colourMaskIndex, newColour.rgb());
		colour->setIcon(QIcon(QPixmap::fromImage(*colourImage)));
	}
}

/**
  * Shows a dialog which lets the user change background colours, then fixes the toolbar icon to reflect the choice
  */
void FormattingToolBar::chooseFontBackgroundColor()
{
	QColor newColour = QColorDialog::getColor(editor->textBackgroundColor(), window(), "Choose font background color");

	if (newColour.isValid())
	{
		editor->setTextBackgroundColor(newColour);

		//fix up the colour in the icon
		backColourImage->setColor(backColourMaskIndex, newColour.rgb());
		textBackgroundColour->setIcon(QIcon(QPixmap::fromImage(*backColourImage)));
	}
}

void FormattingToolBar::addImage()
{
	QString fname = QFileDialog::getOpenFileName(this, "Select an Image to Add", "/", "Images (*.png *.xpm *.jpg *.jpeg *.gif)");

	if (!fname.isNull())
	{
            editor->insertImage(fname);
	}
}

/**
  * Opens a grid-like dialog to create a new table
  */
void FormattingToolBar::addTable()
{
	tableSizeWidget tableSize(this);

	if (tableSize.exec())
	{
            editor->insertTable(tableSize.getCellY(), tableSize.getCellX());
	}
}

/**
  * This is a SLOT which catches the SIGNAL QTextEdit::selectionChanged() and sets the
  * toolbar settings to match the current format which is selected in the document.
  * (This is only done if the user does NOT have a selection highlighted in the document)
  */
void FormattingToolBar::matchCurrentFormat()
{
	QTextCursor cursor = editor->textCursor();
	QTextCharFormat f = cursor.charFormat();

	// only match the format when the user does not have a selection highlighted
	//(if you doubt the reasoning behind this, turn it off and see how crap it is)
	if (cursor.hasSelection())
		return;

	//bold
	bold->blockSignals(true);

	if (f.fontWeight() == QFont::Bold)
		bold->setChecked(true);
	else
		bold->setChecked(false);

	bold->blockSignals(false);

	//italic
	italic->blockSignals(true);

	if (f.fontItalic())
		italic->setChecked(true);
	else
		italic->setChecked(false);

	italic->blockSignals(false);

	//underline
	underline->blockSignals(true);

	if (f.fontUnderline())
		underline->setChecked(true);
	else
		underline->setChecked(false);

	underline->blockSignals(false);

	//font
	font->setCurrentFont(f.font());

	//fontSize
	QString currSize;

	//if point size is 0, then use default size
	if (f.fontPointSize() == 0)
		currSize = QString::number(editor->document()->defaultFont().pointSize());
	else
		currSize = QString::number(f.fontPointSize()).toAscii().data();

	fontSize->blockSignals(true);

	fontSize->setCurrentIndex(fontSize->findText(currSize));

	if (fontSize->currentIndex() == -1)
		fontSize->lineEdit()->setText(currSize);	//set manually if it is not a preset size

	fontSize->blockSignals(false);


	//alignment
	Qt::Alignment align = editor->alignment();

	if (align == Qt::AlignLeft)
		leftAlign->setChecked(true);
	else if (align == Qt::AlignRight)
		rightAlign->setChecked(true);
	else if (align == Qt::AlignHCenter)
		centreAlign->setChecked(true);
	else if (align == Qt::AlignJustify)
		justifyAlign->setChecked(true);

	//lists
	bullets->blockSignals(true);
	numbers->blockSignals(true);

	QTextList *currList = cursor.currentList();

	if (currList != 0)
	{
		if (currList->format().style() >= -3)   //if this is a bulleted point (not numbered)
		{
			bullets->setChecked(true);
			numbers->setChecked(false);
		}
		else
		{
			bullets->setChecked(false);
			numbers->setChecked(true);
		}
	}
	else
	{
		bullets->setChecked(false);
		numbers->setChecked(false);
	}

	bullets->blockSignals(false);
	numbers->blockSignals(false);

	//foreground colour
	QRgb currColour = editor->textColor().rgb();

	if (colourImage->color(colourMaskIndex) != currColour)
	{
		colourImage->setColor(colourMaskIndex, currColour);
		colour->setIcon(QIcon(QPixmap::fromImage(*colourImage)));
	}

	//background colour
	QRgb currBackRgb = editor->textBackgroundColor().rgb();

	if (backColourImage->color(backColourMaskIndex) != currBackRgb)
	{
		backColourImage->setColor(backColourMaskIndex, currBackRgb);
		textBackgroundColour->setIcon(QIcon(QPixmap::fromImage(*backColourImage)));
	}

	//if the style is Qt::NoBrush then display white
	if ((editor->textCursor().atBlockStart() &&
		editor->textCursor().blockCharFormat().background().style() == Qt::NoBrush) ||
		(!editor->textCursor().atBlockStart() &&
		 editor->textCursor().charFormat().background().style() == Qt::NoBrush))
	{
		backColourImage->setColor(backColourMaskIndex, QColor(255,255,255).rgb());
		textBackgroundColour->setIcon(QIcon(QPixmap::fromImage(*backColourImage)));
	}
}

